package com.mars.component.scheduler.utlis;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.mars.common.spring.SpringContextHolder;
import com.mars.component.scheduler.constant.SchedulerConst;
import com.mars.component.scheduler.entity.SchedulerJob;
import com.mars.component.scheduler.exception.SchedulerJobException;

/**
 * Scheduler工具类
 * @类名 SchedulerUtils
 * @日期 2016年12月29日 上午9:05:36
 * @作者 yhaoquan
 * @版权 (c) All Rights Reserved, 2016.
 */
@Component
public class SchedulerUtils {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass()) ;
	
	/**
	 * JobId前缀
	 */
	private final static String JOB_NAME = "TASK_";
	
	@Autowired
	private Scheduler scheduler ;
	
	
	/**
     * 获取触发器key
     */
    public static TriggerKey getTriggerKey(Long jobId, String group) {
    	if(null != group) {
    		return TriggerKey.triggerKey(JOB_NAME + jobId, group) ;
    	} else {
    		return TriggerKey.triggerKey(JOB_NAME + jobId);
    	}
    }
    
    /**
     * 获取jobKey
     */
    public static JobKey getJobKey(Long jobId, String group) {
    	if(null != group) {
    		return JobKey.jobKey(JOB_NAME + jobId, group);
    	} else {
    		return JobKey.jobKey(JOB_NAME + jobId);
    	}
    }

    /**
     * 获取表达式触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId, String group) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId, group));
        } catch (SchedulerException e) {
            throw SchedulerJobException.CRON_TRIGGER_EXCEPTION.logError(e);
        }
    }
    
    /**
     * 通过Spring方式来运行任务
     * @param schedulerJob
     * 			task.beanName 要执行的Spring Bean实例
     * 			task.methodName 要执行的方法
     * 
     */
	public void createScheduleJob(SchedulerJob schedulerJob) {
		try {
			//1: 构建Job信息，运行的类需要实现Job接口
			JobDetail jobDetail = JobBuilder.newJob(ScheduleJobQuartz.class).withIdentity(getJobKey(schedulerJob.getJobId(), schedulerJob.getJobGroup())).withDescription(schedulerJob.getRemarks()).build();
			//1.1: 放入参数，运行时的方法可以获取
			jobDetail.getJobDataMap().put(SchedulerJob.JOB_PARAM_KEY, schedulerJob);
			
			//2: 表达式调度构建器
			CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(schedulerJob.getCronExpression()) ;
			
			//3: 按新的cronExpression表达式构建一个新的trigger
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(schedulerJob.getJobId(), schedulerJob.getJobGroup())).withSchedule(cronSchedule).build() ;
			
			//4: 创建任务调度
			this.scheduler.scheduleJob(jobDetail, trigger) ;
			
			//设置任务状态
			if(null != schedulerJob.getStatus() && schedulerJob.getStatus() == SchedulerConst.ScheduleStatus.PAUSE.getValue()) {
				pauseJob(schedulerJob);
			}
			
			logger.info("任务创建成功【任务状态：{}   任务ID： {}   任务运行BeanName：{}   任务运行的方法：{}   任务触发表达式：{}】", 
					SchedulerConst.ScheduleStatus.getEnum(schedulerJob.getStatus()).getDesc(),
					jobDetail.getKey(),
					SpringContextHolder.getBean(schedulerJob.getBeanName()).getClass(),
					schedulerJob.getMethodName(),
					schedulerJob.getCronExpression());
			
		} catch (Exception e) {
			e.printStackTrace();
			throw SchedulerJobException.CREATE_SCHEDULER_FAILED.logError(e) ;
		}
	}
	
	/**
	 * 修改任务调度的触发时间
	 * @param schedulerJob
	 */
	public void rescheduleJob(SchedulerJob schedulerJob) {
		try {
            TriggerKey triggerKey = getTriggerKey(schedulerJob.getJobId(), schedulerJob.getJobGroup());

            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(schedulerJob.getCronExpression());

            CronTrigger trigger = getCronTrigger(scheduler, schedulerJob.getJobId(), schedulerJob.getJobGroup());
            
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            
            //参数
            trigger.getJobDataMap().put(SchedulerJob.JOB_PARAM_KEY, schedulerJob);
            
            scheduler.rescheduleJob(triggerKey, trigger);
            
            //设置任务状态
            if(null != schedulerJob.getStatus() && schedulerJob.getStatus() == SchedulerConst.ScheduleStatus.PAUSE.getValue()) {
				pauseJob(schedulerJob);
			}
            
        } catch (SchedulerException e) {
            throw SchedulerJobException.RESCHEDULER_JOB_EXCEPTION.logError(e) ;
        }
	}
	
	/**
	 * 暂停任务调度
	 * @param schedulerJob
	 */
	public void pauseJob(SchedulerJob schedulerJob) {
		try {
			scheduler.pauseJob(getJobKey(schedulerJob.getJobId(), schedulerJob.getJobGroup()));
		} catch (SchedulerException e) {
			throw SchedulerJobException.PAUSE_JOB_EXCEPTION.logError(e) ;
		}
	}
	public void pauseJob(Long jobId, String jobGroup) {
		try {
            scheduler.pauseJob(getJobKey(jobId, jobGroup));
        } catch (SchedulerException e) {
            throw SchedulerJobException.PAUSE_JOB_EXCEPTION.logError(e) ;
        }
	}
	
	/**
	 * 恢复任务调度
	 * @param schedulerJob
	 */
	public void resumeJob(SchedulerJob schedulerJob) {
		try {
			scheduler.resumeJob(getJobKey(schedulerJob.getJobId(), schedulerJob.getJobGroup()));
		} catch (SchedulerException e) {
			throw SchedulerJobException.RESUME_EXCEPTION.logError(e) ;
		}
	}
	public void resumeJob(Long jobId, String jobGroup) {
		try {
            scheduler.resumeJob(getJobKey(jobId, jobGroup));
        } catch (SchedulerException e) {
            throw SchedulerJobException.RESUME_EXCEPTION.logError(e) ;
        }
	}
	
	/**
	 * 删除任务
	 * @param schedulerJob
	 */
	public void deleteJob(SchedulerJob schedulerJob) {
		try {
			scheduler.deleteJob(getJobKey(schedulerJob.getJobId(), schedulerJob.getJobGroup()));
		} catch (SchedulerException e) {
			throw SchedulerJobException.DELETE_JOB_EXCEPTION.logError(e) ;
		}
	}
	public void deleteJob(Long jobId, String jobGroup) {
		try {
            scheduler.deleteJob(getJobKey(jobId, jobGroup));
        } catch (SchedulerException e) {
            throw SchedulerJobException.DELETE_JOB_EXCEPTION.logError(e) ;
        }
	}
	
	/**
     * 立即执行任务
     */
	public void runNow(SchedulerJob schedulerJob) {
		try {
			//参数
			JobDataMap dataMap = new JobDataMap();
			dataMap.put(SchedulerJob.JOB_PARAM_KEY, schedulerJob);
			
			scheduler.triggerJob(getJobKey(schedulerJob.getJobId(), schedulerJob.getJobGroup()), dataMap);
		} catch (SchedulerException e) {
			throw SchedulerJobException.RUN_NOW.logError(e) ;
		}
	}
	
}
